package cn.hjh.rpc.producer;

import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.config.TypedStringValue;
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.ManagedList;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import cn.hjh.rpc.check.IRPCCheck;
import cn.hjh.rpc.common.RPCContants;
import cn.hjh.rpc.define.AbstractMQBeanRegister;
import cn.hjh.rpc.define.RPCClientBean;
import cn.hjh.rpc.define.ReplyMode;
import cn.hjh.rpc.register.RPCClientBeanRegister;


/**
 * MQ客户端注册类
 * @author jianhua.huang
 */
@Component
public class ClientBeanRegister extends AbstractMQBeanRegister implements RPCClientBeanRegister {

	private Logger logger = LoggerFactory.getLogger(getClass());

	@Override
	public void register(RPCClientBean bean, ConfigurableListableBeanFactory beanFactory,
			BeanDefinitionRegistry registry) 
	{
		super.init(bean.getConnFactoryRef(), beanFactory, registry);
		checkProperties(bean, beanFactory);
		logger.debug("生成MQ队列客户端：" + bean.getSendQueueName());
		String exchangeName = bean.getExchangeName();
		
		declareDirectExchange(exchangeName, "true", "false");
		String sendQueueId = declareQueue(bean.getSendQueueName(), "true", "false", "false");
		declareBinding(exchangeName, bean.getSendQueueKey(), sendQueueId);
		
		if(ReplyMode.FIX.name().equals(bean.getReplyMode().name()))
		{
			String replyQueueName = bean.getReplyQueueName();
			String replyQueueId = declareQueue(replyQueueName, "true", "false", "false");
			declareBinding(exchangeName, bean.getReplyQueueKey(), replyQueueId);
			registerMessageListenerContainer(bean, replyQueueId, beanFactory);
		}
	}
	
	/**
	 * 属性校验
	 * @author jianhua.huang
	 * */
	private void checkProperties(RPCClientBean bean, ConfigurableListableBeanFactory beanFactory)
	{
		Map<String, IRPCCheck> iChecks = beanFactory.getBeansOfType(IRPCCheck.class);
		for(IRPCCheck check : iChecks.values())
		{
			if(check.isSupport(bean))
			{
				check.doCheck(bean, beanFactory);
			}
		}
	}

	/**
	 * @param queueName
	 * @param beanId
	 */
	protected void registerMessageListenerContainer(RPCClientBean bean, String queueName, 
			ConfigurableListableBeanFactory beanFactory) 
	{
		// 创建一个消息监听容器ListenerContainer
		RootBeanDefinition containerDef = new RootBeanDefinition(SimpleMessageListenerContainer.class);
		String connFactoryRef = bean.getConnFactoryRef();
		if(StringUtils.isEmpty(connFactoryRef))
		{
			connFactoryRef = RPCContants.CONNECTION_FACTORY_BEAN_ID;
		}
		containerDef.getPropertyValues().add(RPCContants.CONNECTION_FACTORY, new RuntimeBeanReference(connFactoryRef));
		// containerDef.getPropertyValues().add("errorHandler", new RuntimeBeanReference(errorHandlerBeanName));
		containerDef.getPropertyValues().add(RPCContants.CONCURRENT_CONSUMERS, bean.getConcurrentConsumers());
		containerDef.getPropertyValues().add(RPCContants.PREFETCH_COUNT, bean.getPrefetchCount());
		containerDef.getPropertyValues().add("defaultRequeueRejected", new TypedStringValue("false"));
		containerDef.getPropertyValues().add("autoStartup", new TypedStringValue("true"));
		containerDef.getPropertyValues().add("autoDeclare", new TypedStringValue("true"));

		// queue队列收集器
		String[] names = StringUtils.commaDelimitedListToStringArray(queueName);
		List<RuntimeBeanReference> values = new ManagedList<RuntimeBeanReference>();
		for (int i = 0; i < names.length; i++) {
			values.add(new RuntimeBeanReference(names[i].trim()));
		}
		containerDef.getPropertyValues().add("queues", values);

		String fixAmqpTemplate = declareAmqpTemplate(bean);
		containerDef.getPropertyValues().add(RPCContants.MESSAGE_LISTENER, new RuntimeBeanReference(fixAmqpTemplate));
		String containerBeanName = BeanDefinitionReaderUtils.generateBeanName(containerDef, beanRegistry);
		BeanComponentDefinition containerDefBeanComponentDefinition = new BeanComponentDefinition(containerDef,
				containerBeanName);
		BeanDefinitionReaderUtils.registerBeanDefinition(containerDefBeanComponentDefinition, beanRegistry);
	}
	

}
